#***************************************************************************
#                                  _   _ ____  _
#  Project                     ___| | | |  _ \| |
#                             / __| | | | |_) | |
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
# 设置可执行文件的名称为 curl
set(EXE_NAME curl)
# 为当前目录添加编译定义，包含 CURL 调试宏
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS "${CURL_DEBUG_MACROS}")

# 初始化生成的 C 源文件列表
set(_curl_cfiles_gen "")
# 初始化生成的头文件列表
set(_curl_hfiles_gen "")
# 初始化编译定义列表
set(_curl_definitions "")

# 若启用构建 curl 手册页且存在手册生成工具
if(ENABLE_CURL_MANUAL AND HAVE_MANUAL_TOOLS)
  # 将 USE_MANUAL 添加到编译定义列表中
  list(APPEND _curl_definitions "USE_MANUAL")
  # 添加自定义命令，用于生成 tool_hugehelp.c 文件
  add_custom_command(
    # 输出文件为 tool_hugehelp.c
    OUTPUT "tool_hugehelp.c"
    # 向 tool_hugehelp.c 文件写入 #include "tool_setup.h"
    COMMAND ${CMAKE_COMMAND} -E echo "#include \"tool_setup.h\"" > "tool_hugehelp.c"
    # 向 tool_hugehelp.c 文件追加 #ifndef HAVE_LIBZ
    COMMAND ${CMAKE_COMMAND} -E echo "#ifndef HAVE_LIBZ" >> "tool_hugehelp.c"
    # 调用 mkhelp.pl 脚本处理 CURL_ASCIIPAGE 文件内容，并追加到 tool_hugehelp.c 文件中
    COMMAND "${PERL_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/mkhelp.pl"    < "${CURL_ASCIIPAGE}" >> "tool_hugehelp.c"
    # 向 tool_hugehelp.c 文件追加 #else
    COMMAND ${CMAKE_COMMAND} -E echo "#else" >> "tool_hugehelp.c"
    # 调用 mkhelp.pl 脚本带 -c 参数处理 CURL_ASCIIPAGE 文件内容，并追加到 tool_hugehelp.c 文件中
    COMMAND "${PERL_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/mkhelp.pl" -c < "${CURL_ASCIIPAGE}" >> "tool_hugehelp.c"
    # 向 tool_hugehelp.c 文件追加 #endif /* HAVE_LIBZ */
    COMMAND ${CMAKE_COMMAND} -E echo "#endif /* HAVE_LIBZ */" >> "tool_hugehelp.c"
    # 该命令依赖于 generate-curl.1 目标、mkhelp.pl 脚本、tool_hugehelp.h 文件和 CURL_ASCIIPAGE 文件
    DEPENDS
      generate-curl.1
      "${CMAKE_CURRENT_SOURCE_DIR}/mkhelp.pl"
      "${CMAKE_CURRENT_SOURCE_DIR}/tool_hugehelp.h"
      "${CURL_ASCIIPAGE}"
    # 确保命令参数按原样传递
    VERBATIM)
  # 将生成的 tool_hugehelp.c 文件添加到生成的 C 源文件列表中
  list(APPEND _curl_cfiles_gen "tool_hugehelp.c")
  # 将 tool_hugehelp.h 文件添加到生成的头文件列表中
  list(APPEND _curl_hfiles_gen "tool_hugehelp.h")
endif()

# 若设置了要嵌入的 CA 证书包
if(CURL_CA_EMBED_SET)
  # 若找到 Perl 解释器
  if(PERL_FOUND)
    # 将 CURL_CA_EMBED 添加到编译定义列表中
    list(APPEND _curl_definitions "CURL_CA_EMBED")
    # 添加自定义命令，用于生成 tool_ca_embed.c 文件
    add_custom_command(
      # 输出文件为 tool_ca_embed.c
      OUTPUT "tool_ca_embed.c"
      # 调用 mk-file-embed.pl 脚本处理 CURL_CA_EMBED 文件内容，并输出到 tool_ca_embed.c 文件中
      COMMAND "${PERL_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/mk-file-embed.pl" --var curl_ca_embed
        < "${CURL_CA_EMBED}" > "tool_ca_embed.c"
      # 该命令依赖于 mk-file-embed.pl 脚本和 CURL_CA_EMBED 文件
      DEPENDS
        "${CMAKE_CURRENT_SOURCE_DIR}/mk-file-embed.pl"
        "${CURL_CA_EMBED}"
      # 确保命令参数按原样传递
      VERBATIM)
    # 将生成的 tool_ca_embed.c 文件添加到生成的 C 源文件列表中
    list(APPEND _curl_cfiles_gen "tool_ca_embed.c")
  else()
    # 若未找到 Perl 解释器，输出警告信息，提示不会嵌入 CA 证书包
    message(WARNING "Perl not found. Will not embed the CA bundle.")
  endif()
endif()

# 转换 Makefile.inc 文件为 CMake 可识别的文件
# 并获取 'CURL_CFILES', 'CURLX_CFILES', 'CURL_HFILES', 'CURLTOOL_LIBCURL_CFILES' 变量
curl_transform_makefile_inc("Makefile.inc" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake")
# 包含转换后的 Makefile.inc.cmake 文件
include("${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake")

# 若为 Windows 平台
if(WIN32)
  # 将 curl.rc 文件添加到 CURL_CFILES 列表中
  list(APPEND CURL_CFILES "curl.rc")
endif()

# 若构建静态版的 curl
if(BUILD_STATIC_CURL)
  # 将 CURLTOOL_LIBCURL_CFILES 赋值给 CURLX_CFILES
  set(CURLX_CFILES ${CURLTOOL_LIBCURL_CFILES})
endif()

# 若启用 CURL 调试
if(ENABLE_CURLDEBUG)
  # 必须单独编译此源文件，以避免 memdebug.h 重定义影响它们
  set_source_files_properties("../lib/curl_multibyte.c" PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON)
endif()

# 添加可执行文件目标
add_executable(
  # 可执行文件的名称
  ${EXE_NAME}
  # 源文件和头文件列表
  ${CURL_CFILES} ${_curl_cfiles_gen} ${CURLX_CFILES} ${CURL_HFILES} ${_curl_hfiles_gen}
)
# 为可执行文件添加私有编译定义
target_compile_definitions(${EXE_NAME} PRIVATE ${_curl_definitions})

# 为 macOS 设置 RPATH 使用 @loader_path
if(APPLE)
    set(CMAKE_INSTALL_RPATH "@loader_path/../lib")  # 相对于可执行文件的路径
endif(APPLE)

# 为 linux 设置 RPATH 使用 $ORIGIN
if(UNIX AND NOT APPLE)
    set(CMAKE_INSTALL_RPATH "\$ORIGIN/../lib")  # 相对于可执行文件的路径
endif()
# 为可执行文件添加别名
add_executable(
  ${PROJECT_NAME}::${EXE_NAME}
  ALIAS ${EXE_NAME}
)

# 添加一个静态库目标，仅用于单元测试
add_library(
  # 库的名称
  curltool
  # 静态库类型
  STATIC
  # 从默认构建目标中排除
  EXCLUDE_FROM_ALL
  # 源文件和头文件列表
  ${CURL_CFILES} ${CURLTOOL_LIBCURL_CFILES} ${CURL_HFILES}
)
# 为 curltool 库添加公共编译定义，表明正在进行单元测试和使用静态库
target_compile_definitions(curltool PUBLIC "UNITTESTS" "CURL_STATICLIB")
# 为 curltool 库添加私有链接库
target_link_libraries(curltool PRIVATE ${CURL_LIBS})

# 若 CURL 支持链接时优化
if(CURL_HAS_LTO)
  # 为可执行文件启用链接时优化
  set_target_properties(${EXE_NAME} PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()

# 若启用 Unicode 支持，且使用 MinGW 编译器，且不是 MinGW32CE 环境
if(ENABLE_UNICODE AND MINGW AND NOT MINGW32CE)
  # 为可执行文件添加 -municode 链接选项
  target_link_libraries(${EXE_NAME} "-municode")
endif()

# 为不同类型的源文件和头文件创建 Visual Studio 解决方案中的源文件分组
source_group("curlX source files" FILES ${CURLX_CFILES})
source_group("curl source files" FILES ${CURL_CFILES} ${_curl_cfiles_gen})
source_group("curl header files" FILES ${CURL_HFILES} ${_curl_hfiles_gen})

# 添加包含目录，以便编译器能够找到所需的头文件
include_directories(
  # 用于查找 curl_config.h
  "${PROJECT_BINARY_DIR}/lib"
  # 用于查找 curl_setup.h
  "${PROJECT_SOURCE_DIR}/lib"
  # 由于 tool_hugehelp.c 在二进制目录生成，这里用于查找 tool_hugehelp.h
  "${PROJECT_SOURCE_DIR}/src"
)

# 链接库到 curl 可执行文件
target_link_libraries(${EXE_NAME} ${LIB_SELECTED_FOR_EXE} ${CURL_LIBS})

################################################################################

# 安装 curl 可执行文件
install(TARGETS ${EXE_NAME} EXPORT ${TARGETS_EXPORT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
# 导出 curl 可执行文件目标到指定文件，并设置命名空间
export(TARGETS ${EXE_NAME}
  FILE "${PROJECT_BINARY_DIR}/curl-target.cmake"
  NAMESPACE ${PROJECT_NAME}::
)
